using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;

/// <summary>
/// 📂 文件/文件夹选择助手（基于 Windows API）
/// </summary>
public static class FolderBrowserHelper
{
    #region Windows API 结构体

    /// <summary>
    /// 📂 选择文件对话框结构体（与 Windows API 交互）
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private class OpenFileName
    {
        public int structSize = 0;
        public IntPtr dlgOwner = IntPtr.Zero;
        public IntPtr instance = IntPtr.Zero;
        public string filter = null;
        public string customFilter = null;
        public int maxCustFilter = 0;
        public int filterIndex = 0;
        public string file = null;
        public int maxFile = 0;
        public string fileTitle = null;
        public int maxFileTitle = 0;
        public string initialDir = null;
        public string title = null;
        public int flags = 0;
        public short fileOffset = 0;
        public short fileExtension = 0;
        public string defExt = null;
        public IntPtr custData = IntPtr.Zero;
        public IntPtr hook = IntPtr.Zero;
        public string templateName = null;
        public IntPtr reservedPtr = IntPtr.Zero;
        public int reservedInt = 0;
        public int flagsEx = 0;
    }

    /// <summary>
    /// 📁 选择文件夹对话框结构体（与 Windows API 交互）
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private class OpenDialogDir
    {
        public IntPtr hwndOwner = IntPtr.Zero;
        public IntPtr pidlRoot = IntPtr.Zero;
        public string pszDisplayName = null;
        public string lpszTitle = null;
        public uint ulFlags = 0;
        public IntPtr lpfn = IntPtr.Zero;
        public IntPtr lParam = IntPtr.Zero;
        public int iImage = 0;
    }

    #endregion

    #region Windows API 导入

    [DllImport("Comdlg32.dll", CharSet = CharSet.Auto)]
    private static extern bool GetOpenFileName([In, Out] OpenFileName ofn);

    [DllImport("Comdlg32.dll", CharSet = CharSet.Auto)]
    private static extern bool GetSaveFileName([In, Out] OpenFileName ofn);

    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr SHBrowseForFolder([In, Out] OpenDialogDir ofn);

    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
    private static extern bool SHGetPathFromIDList([In] IntPtr pidl, [In, Out] char[] fileName);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPTStr)] string lParam);

    #endregion

    #region 文件类型筛选器

    public const string IMAGEFILTER = "图片文件(*.jpg;*.png)\0*.jpg;*.png";
    public const string ALLFILTER = "所有文件(*.*)\0*.*";
    public const string MP4FILTER = "视频文件(*.mp4)\0*.mp4";
    public const string EXCELFILTER = "Excel文件(*.xlsx;*.xls)\0*.xlsx;*.xls";

    #endregion

    /// <summary>
    /// 🗑️ 清除 Windows 对话框缓存（防止标题错乱）
    /// </summary>
    /// <param name="hwnd">窗口句柄</param>
    /// <param name="title">窗口标题</param>
    private static void ClearDialogCache(IntPtr hwnd, string title)
    {
        SendMessage(hwnd, 0x000C, IntPtr.Zero, title);
    }

    /// <summary>
    /// 📂 选择文件
    /// </summary>
    /// <param name="filter">文件类型筛选器（如 FolderBrowserHelper.IMAGEFILTER）</param>
    /// <returns>返回选择的文件路径，若未选择则返回 null</returns>
    public static string SelectFile(string filter)
    {
        try
        {
            OpenFileName openFileName = new OpenFileName
            {
                structSize = Marshal.SizeOf(typeof(OpenFileName)),
                filter = Encoding.Default.GetString(Encoding.Default.GetBytes(filter)), // 文件类型筛选
                file = new string(new char[256]), // 选中的文件路径
                maxFile = 256,
                fileTitle = new string(new char[64]),
                maxFileTitle = 64,
                title = Encoding.Default.GetString(Encoding.Default.GetBytes("选择文件")), // 对话框标题
                flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008 // 设置对话框标志
            };

            // 清除对话框缓存，避免标题错乱
            ClearDialogCache(openFileName.dlgOwner, openFileName.title);

            // 打开文件选择对话框
            if (GetOpenFileName(openFileName))
            {
                string filepath = openFileName.file;
                if (File.Exists(filepath))
                {
                    return filepath;
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogError($"❌ 选择文件失败: {e.Message}");
        }
        return null;
    }

    /// <summary>
    /// 📁 选择文件夹
    /// </summary>
    /// <returns>返回选择的文件夹路径，若未选择则返回 null</returns>
    public static string SelectFolder()
    {
        try
        {
            OpenDialogDir openDialogDir = new OpenDialogDir
            {
                lpszTitle = "选择文件夹",
                ulFlags = 0x00000040 // 允许新建文件夹
            };

            IntPtr pidl = SHBrowseForFolder(openDialogDir);
            if (pidl != IntPtr.Zero)
            {
                char[] path = new char[260];
                if (SHGetPathFromIDList(pidl, path))
                {
                    return new string(path).TrimEnd('\0');
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogError($"❌ 选择文件夹失败: {e.Message}");
        }
        return null;
    }
}
